package org.liuhy.node
{
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import mx.collections.ArrayCollection;
	import mx.containers.Canvas;
	import mx.controls.TextArea;
	import mx.core.DragSource;
	import mx.core.UIComponent;
	import mx.core.UITextField;
	import mx.events.DragEvent;
	import mx.managers.CursorManager;
	import mx.managers.DragManager;
	
	import org.CacheUtils;
	import org.liuhy.FlowPanel;
	import org.liuhy.control.UpDownCursor;
	import org.liuhy.control.XCursor;
	import org.liuhy.jbpm4.utils.JbpmRectLineUtils;
	import org.liuhy.line.AbstractLine;
	import org.liuhy.line.ArrowLineNode;
	import org.liuhy.line.CLine;
	import org.liuhy.line.FromLineNode;
	import org.liuhy.line.LineNode;
	import org.liuhy.node.focus.BottomNode;
	import org.liuhy.node.focus.FocusNode;
	import org.liuhy.node.focus.LeftNode;
	import org.liuhy.node.focus.RightNode;
	import org.liuhy.node.focus.TopNode;
	
	public class FlowNode extends UIComponent
	{
		public var _top_node:TopNode;
		public var _bottom_node:BottomNode;
		public var _left_node:LeftNode;
		public var _right_node:RightNode;
		public var _textArea:TextArea = new TextArea();
		private var _flowNodeId:String = "";
		private var _borderColor:uint 				=0x000000;
		private var _focusNodeBorderColor:uint		=0x000000;
		private var _focusNodeBackgroundColor:uint	=0x000000;
		public var _inLineList:ArrayCollection = new ArrayCollection();	 //入线集合；
		public var _outLineList:ArrayCollection = new ArrayCollection(); //出线集合；
		private var _mousePoint:Point = null;
		private var _currentfocusNode:FocusNode = null;
		private var _oldX:int = 0;
		private var _oldY:int = 0;
		public function FlowNode(p_x:int,p_y:int,p_width:int,p_height:int)
		{
			this.x = p_x;
			this.y = p_y;
			this._oldX = p_x;
			this._oldY = p_y;
			this.width	= p_width;
			this.height = p_height;			

			this.addEventListener(KeyboardEvent.KEY_DOWN,onDelete);
			this.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE,onFocusChange);			
			this.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);

			this._textArea.width 	= this.width  - 20;
			this._textArea.height 	= this.height - 20;
			this._textArea.setStyle("backgroundAlpha","0");
			this._textArea.setStyle("textAlign","center");
			this._textArea.setStyle("borderThickness","0");
			this._textArea.x	= 10;
			this._textArea.y    = 10;					
			this._textArea.enabled = false;
			this.doubleClickEnabled =true;

			this._textArea.addEventListener(MouseEvent.CLICK,onTextAreaClick);
			this._textArea.addEventListener(MouseEvent.DOUBLE_CLICK,onTextAreaDoubleClick);
			this._textArea.addEventListener(MouseEvent.MOUSE_MOVE,function(event:MouseEvent):void{
				var _txt:TextArea = event.currentTarget as TextArea;
				if(_txt.enabled){
					event.stopPropagation();
				}
			});
			this._textArea.addEventListener(MouseEvent.MOUSE_OVER,function(event:MouseEvent):void{
				var _txt:TextArea = event.currentTarget as TextArea;
				if(_txt.enabled){
					CursorManager.removeAllCursors();
				}else{
					CursorManager.setCursor(UpDownCursor);
				}		
			});
			this._textArea.addEventListener(MouseEvent.MOUSE_OUT,function(event:MouseEvent):void{
				CursorManager.removeAllCursors();
			});
			this.addEventListener(DragEvent.DRAG_ENTER,onLineNodeEnter);
			this.addEventListener(DragEvent.DRAG_DROP,onLineNodeDrop);
			this.addEventListener(DragEvent.DRAG_OVER,onLineNodeOver);
			this.addEventListener(DragEvent.DRAG_EXIT,onLineNodeExit);
			this.addEventListener(MouseEvent.CLICK,onClick);
			this.addChild(this._textArea);
			this._top_node 		= new TopNode(this.width/2-5,0);
			this._left_node 	= new LeftNode(0,this.height/2-5);
			this._right_node 	= new RightNode(this.width-10,this.height/2-5);
			this._bottom_node	= new BottomNode(this.width/2-5,this.height-10);		
			this._wrap_focus_node(this._top_node);
			this._wrap_focus_node(this._left_node);
			this._wrap_focus_node(this._right_node);
			this._wrap_focus_node(this._bottom_node);			
		}
		public function onClick(p_event:MouseEvent):void{
//				p_event.stopPropagation();
//			}else			if(this._textArea.enabled){
//{
				this.stage.focus = this;
//			}
			p_event.stopPropagation();
		}
		public function onMouseMove(event:MouseEvent):void{
			var dragInitiator:FlowNode = FlowNode(event.currentTarget);
            var ds:DragSource = new DragSource();
            ds.addData(this,"flowNode");
            DragManager.doDrag(dragInitiator, ds, event);
			this.draw();
			_mousePoint = new Point(event.stageX,event.stageY);
//			event.stopPropagation();
		}
		public function flowNodeDrop(event:DragEvent):void{
			var _panel:FlowPanel = this.parent as FlowPanel;
			CacheUtils.push(_panel.exportXML());
			
			this.x = this.x + (event.stageX-_mousePoint.x);
			this.y = this.y + (event.stageY-_mousePoint.y);
			if(_inLineList.length>0){
				//调整箭头线;
				for(var i:int=0;i<_inLineList.length;i++){
					var _inLine1:AbstractLine = _inLineList.getItemAt(i) as AbstractLine;
					var _cLine:CLine = _inLine1.parent as CLine;
//					_inLine1.arrowLineNode.x = this.x + _inLine1.in_flowFocusNode._x;
//					_inLine1.arrowLineNode.y = this.y + _inLine1.in_flowFocusNode._y;
					_inLine1.in_flowFocusNode.adjustULine(_inLine1);
					//调整线段标题;
					_cLine.adjustTitle(null);			//ok
				}
			}
			if(_outLineList.length>0){
				//调整开始线;
				for(var i:int=0;i<_outLineList.length;i++){
					var _outLine1:AbstractLine = _outLineList.getItemAt(i) as AbstractLine;
					var _cLine:CLine = _outLine1.parent as CLine;
					_outLine1.fromLineNode.x = this.x + _outLine1.out_flowFocusNode._x;
					_outLine1.fromLineNode.y = this.y + _outLine1.out_flowFocusNode._y;
					_outLine1.out_flowFocusNode.adjustULine(_outLine1);
					//调整线段标题;
					_cLine.adjustTitle(null);
				}
			}
			this._oldX = this.x;
			this._oldY = this.y;
			
		}
		public function onLineNodeEnter(p_event:DragEvent):void{
			if(p_event.dragInitiator is LineNode){
				DragManager.acceptDragDrop(UIComponent(p_event.currentTarget));
				this._borderColor = 0xFF0000;
				this.draw();
				CursorManager.setCursor(XCursor);
			}
		}
		public function onLineNodeOver(p_event:DragEvent):void{
			var _lineNode:LineNode = p_event.dragInitiator as LineNode;
			var _line:AbstractLine = _lineNode.parent as AbstractLine;
			var _p:Point = new Point(p_event.localX,p_event.localY);
			var _focusNode:FocusNode = this.getNearFocusNode(_p);
			this.setFocusVisible(true);
			if(this._currentfocusNode == _focusNode){
				_focusNode.setOnFocusNode();
			}else{
				if(null==this._currentfocusNode){
					_focusNode.setOnFocusNode();
					this._currentfocusNode = _focusNode;
				}else{
					this._currentfocusNode.setOutFocusNode();
					this._currentfocusNode = _focusNode;
				}				
			}			
			if(_lineNode is FromLineNode){
				_line.fromNodeFocusAdjustVirtualLine(_focusNode);
			}else if(_lineNode is ArrowLineNode){
				_line.arrowNodeFocusAdjustVirtualLine(_focusNode);
			}
			CursorManager.setCursor(XCursor);
				
		}
		public function onLineNodeDrop(p_event:DragEvent):void{		
			var _lineNode:LineNode = p_event.dragInitiator as LineNode;
			var _line:AbstractLine = _lineNode.parent as AbstractLine;
			var _cLine:CLine = _line.parent as CLine;
			var _p:Point = new Point(p_event.localX,p_event.localY);
			if(_lineNode is FromLineNode){				
				_line.focusNodeDropFromLine(this.getNearFocusNode(_p));
			}else if(_lineNode is ArrowLineNode){
				_line.focusNodeDropArrowLine(this.getNearFocusNode(_p));
			}
			this._borderColor = 0x000000;
			this.draw();
			CursorManager.removeAllCursors();	
			this._currentfocusNode.setStyle("borderColor",0xFFFFFF);
			this._currentfocusNode.setStyle("backgroundAlpha","0");
			this._currentfocusNode.setStyle("backgroundColor",0x000000);	
			_cLine.adjustTitle(null);		
		}
		public function onLineNodeExit(p_event:DragEvent):void{
			this._borderColor = 0x000000;
			this.draw();
			CursorManager.removeAllCursors();	
			if(null!=this._currentfocusNode){
				this._currentfocusNode.setStyle("borderColor",0xFFFFFF);
				this._currentfocusNode.setStyle("backgroundAlpha","0");
				this._currentfocusNode.setStyle("backgroundColor",0x000000);
			}	
		}
		public function getNearFocusNode(p_point:Point):FocusNode{
			var _left:int	 = Point.distance(p_point,new Point(0,this.height/2));
			var _right:int 	 = Point.distance(p_point,new Point(this.width,this.height/2));
			var _top:int 	 = Point.distance(p_point,new Point(this.width/2,0));
			var _bottom:int	 = Point.distance(p_point,new Point(this.width/2,this.height));
			var _min:int = Math.min(_left,_right,_top,_bottom);
			if(_left==_min){
				return this._left_node;
			}else if(_right==_min){
				return this._right_node;
			}else if(_top==_min){
				return this._top_node;
			}else if(_bottom==_min){
				return this._bottom_node;
			}
			return null;
		}
		public function getGlobalNearFocusNode(p_point:Point):FocusNode{
			var _left:int	 = Point.distance(p_point,new Point(this.x,this.y+this.height/2));
			var _right:int 	 = Point.distance(p_point,new Point(this.x+this.width,this.y+this.height/2));
			var _top:int 	 = Point.distance(p_point,new Point(this.x+this.width/2,this.y));
			var _bottom:int	 = Point.distance(p_point,new Point(this.x+this.width/2,this.y+this.height));
			var _min:int = Math.min(_left,_right,_top,_bottom);
			if(_left==_min){
				return this._left_node;
			}else if(_right==_min){
				return this._right_node;
			}else if(_top==_min){
				return this._top_node;
			}else if(_bottom==_min){
				return this._bottom_node;
			}
			return null;
		}
		//线段,开始节点落在上面;
		public function fromNodeDrop(p_event:DragEvent):void{
			
		}
		//线段,箭头节点落在上面;
		public function arrowNodeDrop(p_event:DragEvent):void{
			
		}
		public function reDraw():void{
			this._textArea.width 	= this.width  - 20;
			this._textArea.height 	= this.height - 20;
			this._top_node.x  	= this.width/2 - 5;
			this._left_node.y 	= this.height/2 - 5; 			
			this._right_node.x 	= this.width - 10; 
			this._right_node.y 	= this.height/2 - 5; 			
			this._bottom_node.x = this.width/2 - 5; 
			this._bottom_node.y = this.height - 10; 
			this.draw();
		}
		public function onTextAreaClick(event:MouseEvent):void{
			this.focusNodeBackgroundColor	 = 0x00FF00;
			this.focusNodeBorderColor		 = 0x00FF00;
			this.borderColor 				 = 0x00FF00;
			setFocusVisible(true);
			var _canvas:Canvas = this.parent as Canvas;
			_canvas.setChildIndex(this,_canvas.numChildren-1);
			if(this._textArea.enabled){
				event.stopPropagation();
			}
			this.draw();
		}
		public function onTextAreaDoubleClick(event:MouseEvent):void{
			this._textArea.enabled = true;			
			this._textArea.stage.focus = this._textArea;			
		}
		public function onFocusChange(event:FocusEvent):void{
			//调整文本框高度;
			this._textArea.enabled = false;
			this.focusNodeBackgroundColor = 0xFFFFFF;
			this.focusNodeBorderColor = 0xFFFFFF;
			this.borderColor = 0x000000;
			this.draw();
//			var _panel:FlowPanel = this.parent as FlowPanel;
//			CacheUtils.push(_panel.exportXML());
		}
		public function setFocusVisible(p_bln:Boolean):void{
			this._top_node.visible 		= p_bln;
			this._left_node.visible 	= p_bln;
			this._bottom_node.visible 	= p_bln;
			this._right_node.visible 	= p_bln;
		}
		public function onDelete(event:KeyboardEvent):void{
			if(event.target is UITextField) return;
			if(127==event.charCode){
				for(var i:int=0;i<this._inLineList.length;i++){
					var _line:AbstractLine = this._inLineList.getItemAt(i) as AbstractLine;
					_line.in_flowFocusNode = null;
					this.removeInLine(_line);
				}
				for(var i:int=0;i<this._outLineList.length;i++){
					var _line:AbstractLine = this._outLineList.getItemAt(i) as AbstractLine;
					_line.out_flowFocusNode = null;
					this.removeOutLine(_line);
				}
				var _canvas:Canvas = this.parent as Canvas;
				_canvas.removeChild(this);
			}
		}
		public function draw():void{
		}
		public function set focusNodeBackgroundColor(p_color:uint):void{
			this._focusNodeBackgroundColor = p_color;
			//
			this._top_node.setStyle("backgroundColor",this._focusNodeBackgroundColor);
			this._left_node.setStyle("backgroundColor",this._focusNodeBackgroundColor);
			this._right_node.setStyle("backgroundColor",this._focusNodeBackgroundColor);
			this._bottom_node.setStyle("backgroundColor",this._focusNodeBackgroundColor);
		}
		public function get focusNodeBackgroundColor():uint{
			return this._focusNodeBackgroundColor;
		}
		public function set borderColor(p_color:uint):void{
			this._borderColor = p_color;
		}
		public function get borderColor():uint{
			return this._borderColor;
		}
		public function set focusNodeBorderColor(p_color:uint):void{
			this._focusNodeBorderColor = p_color; 
			this._top_node.setStyle("borderColor",this._focusNodeBorderColor);
			this._left_node.setStyle("borderColor",this._focusNodeBorderColor);
			this._right_node.setStyle("borderColor",this._focusNodeBorderColor);
			this._bottom_node.setStyle("borderColor",this._focusNodeBorderColor);
		}
		public function get focusNodeBorderColor():uint{
			return this._focusNodeBorderColor;
		}
		//是否允许箭头放下;
		public function isPermitAllowDrop():Boolean{
			return true;
		}
		//是否允许开始放下
		public function isPermitFromDrop():Boolean{
			return true;
		}
			
		public function get type():String{
			return "";
		}
		public function get _x():int{
			return this.x + 5;			
		}
		public function get _y():int{
			return this.y + 5;
		}
		public function get oldX():int{
			return _oldX;
		}
		public function set oldX(p_oldX:int):void{
			this._oldX = p_oldX;
		}
		public function get oldY():int{
			return _oldY;
		}
		public function set oldY(p_oldY:int):void{
			this._oldY = p_oldY;
		}		
		public function get title():String{
			return _textArea.text;
		}
		public function set title(p_title:String):void{
			this._textArea.text = p_title;
		}
		public function get flowNodeId():String{
			return this._flowNodeId;
		}
		public function set flowNodeId(p_flowNodeId:String):void{
			this._flowNodeId = p_flowNodeId;
		}
		public function addInLine(p_uLine:AbstractLine):void{
			if(!_inLineList.contains(p_uLine)){
				_inLineList.addItem(p_uLine);
			}
		}
		public function removeInLine(p_uLine:AbstractLine):void{
			for(var i:int=0;i<_inLineList.length;i++){
				var _in:AbstractLine = _inLineList.getItemAt(i) as AbstractLine;
				if(p_uLine==_in){
					_inLineList.removeItemAt(i);
					break;
				}
			}			
		}
		public function addOutLine(p_uLine:AbstractLine):void{
			if(!_outLineList.contains(p_uLine)){
				_outLineList.addItem(p_uLine);
			}
		}
		public function removeOutLine(p_uLine:AbstractLine):void{
			for(var i:int=0;i<_outLineList.length;i++){
				if(p_uLine == _outLineList.getItemAt(i)){
					_outLineList.removeItemAt(i);
					break;
				}
			}			
		}
		private function _wrap_focus_node(p_focusNode:FocusNode):void{
			p_focusNode.width = 10;
			p_focusNode.height = 10;
			p_focusNode.setStyle("borderStyle","solid");
			p_focusNode.setStyle("borderColor","#FFFFFF");
			p_focusNode.setStyle("backgroundColor","#FFFFFF");
			p_focusNode.setStyle("backgroundAlpha","0");
				
			this.addChild(p_focusNode);			
//			p_focusNode.addEventListener(DragEvent.DRAG_ENTER,onDragEnter);
//			p_focusNode.addEventListener(DragEvent.DRAG_DROP,p_focusNode.lineNodeDrop);
//			p_focusNode.addEventListener(DragEvent.DRAG_EXIT,onDragExit);
		}
		public function getFocusNode(p_pos:String):FocusNode{
			if(p_pos==this._bottom_node.pos) return this._bottom_node;
			if(p_pos==this._top_node.pos) return this._top_node;
			if(p_pos==this._right_node.pos) return this._right_node;
			if(p_pos==this._left_node.pos) return this._left_node;
			return null;
		}
		//转化为XML
		public function toXML():String{
			var _array:ArrayCollection = this._outLineList;
			var _str:String = "<" + this.type + " name=\"" + this.title + "\" g=\"" + this.x +"," +this.y + "," + this.width + "," + this.height + "\">";
			for(var i:int=0;i<_array.length;i++){
				var _line:AbstractLine = _array[i] as AbstractLine;
				var _cLine:CLine = _line.parent as CLine;
				var _arrow:FlowNode = _cLine.getArrowFlowNode();
				var _to:String = "";
				if(null!=_arrow){
					_to = _arrow.title;
				}
				var _tran:String = "";
				if(0==JbpmRectLineUtils.getJbpmCLinePosStrs(_cLine).length){
					_tran= "<transition name=\"" + _cLine.title + "\" " + " to=\"" + _to + "\"/>\n";
				}else{
					_tran= "<transition name=\"" + _cLine.title + "\" " + " to=\"" + _to + "\" g=\"" + JbpmRectLineUtils.getJbpmCLinePosStrs(_cLine) + "\"/>\n";
				}
				_str = _str +  _tran ;
			}
			return _str + "</" + this.type + ">";
		}
	}
}